package eu.catengine.renderable.shape;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.microedition.khronos.opengles.GL10;

import eu.catengine.primitive.Point;
import eu.catengine.primitive.Size;

/**
 * Klasa przechowująca dane dotyczące linii wyświetlanej w scenie. <br>
 * <br>
 * Punt zaczepienia obiektu (anchor point) znajduje się w lewym górnym rogu.
 * 
 * @author mbienkowski
 */
public class Line extends Shape
{
    private float mWidth;

    /**
     * Tworzy linię.
     * 
     * @param p1
     *            <code>Point</code> Punkt początkowy.
     * @param p2
     *            <code>Point</code> Punkt końcowy.
     */
    public Line(Point p1, Point p2)
    {
	setLineData("", p1.x, p1.y, p2.x, p2.y, 1);
    }

    /**
     * Tworzy linię.
     * 
     * @param x1
     *            <code>float</code> Współrzędna X punktu początkowego.
     * @param y1
     *            <code>float</code> Współrzędna Y punktu początkowego.
     * @param x2
     *            <code>float</code> Współrzędna X punktu końcowego.
     * @param y2
     *            <code>float</code> Współrzędna Y punktu końcowego.
     */
    public Line(float x1, float y1, float x2, float y2)
    {
	setLineData("", x1, y1, x2, y2, 1);
    }

    /**
     * Tworzy linię.
     * 
     * @param id
     *            <code>String</code> Nazwa obiektu.
     * @param p1
     *            <code>Point</code> Punkt początkowy.
     * @param p2
     *            <code>Point</code> Punkt końcowy.
     */
    public Line(String id, Point p1, Point p2)
    {
	setLineData(id, p1.x, p1.y, p2.x, p2.y, 1);
    }

    /**
     * Tworzy linię.
     * 
     * @param id
     *            <code>String</code> Nazwa obiektu.
     * @param x1
     *            <code>float</code> Współrzędna X punktu początkowego.
     * @param y1
     *            <code>float</code> Współrzędna Y punktu początkowego.
     * @param x2
     *            <code>float</code> Współrzędna X punktu końcowego.
     * @param y2
     *            <code>float</code> Współrzędna Y punktu końcowego.
     */
    public Line(String id, float x1, float y1, float x2, float y2)
    {
	setLineData(id, x1, y1, x2, y2, 1);
    }

    /**
     * Tworzy linię.
     * 
     * @param id
     *            <code>String</code> Nazwa obiektu.
     * @param p1
     *            <code>Point</code> Punkt początkowy.
     * @param p2
     *            <code>Point</code> Punkt końcowy.
     * @param width
     *            <code>float</code> Grubość linii.
     */
    public Line(String id, Point p1, Point p2, float width)
    {
	setLineData(id, p1.x, p1.y, p2.x, p2.y, width);
    }

    /**
     * Tworzy linię.
     * 
     * @param id
     *            <code>String</code> Nazwa obiektu.
     * @param x1
     *            <code>float</code> Współrzędna X punktu początkowego.
     * @param y1
     *            <code>float</code> Współrzędna Y punktu początkowego.
     * @param x2
     *            <code>float</code> Współrzędna X punktu końcowego.
     * @param y2
     *            <code>float</code> Współrzędna Y punktu końcowego.
     * @param width
     *            <code>float</code> Grubość linii.
     */
    public Line(String id, float x1, float y1, float x2, float y2, float width)
    {
	setLineData(id, x1, y1, x2, y2, width);
    }

    private void setLineData(String id, float x1, float y1, float x2, float y2, float width)
    {
	this.setName(id);
	this.mWidth = width;
	this.mSize = new Size(x1 - x2, y1 - y2);
	this.mVertices = new float[] { x1, y1, // V1 - bottom left
		x2, y2, // V2 - top left
	};
	this.mVerticesCount = this.mVertices.length / 2;
	ByteBuffer byteBuffer = ByteBuffer.allocateDirect(this.mVertices.length * 4);
	byteBuffer.order(ByteOrder.nativeOrder());
	this.mVertexBuffer = byteBuffer.asFloatBuffer();
	this.mVertexBuffer.put(this.mVertices);
	this.mVertexBuffer.position(0);
    }

    @Override
    public void draw(GL10 gl)
    {
	if (mVisible == false)
	    return;

	gl.glPushMatrix();
	gl.glEnable(GL10.GL_BLEND);
	gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
	gl.glEnable(GL10.GL_ALPHA_BITS);
	gl.glColor4f(mColor.red, mColor.green, mColor.blue, mColor.alpha);
	gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
	gl.glFrontFace(GL10.GL_CW);
	gl.glVertexPointer(2, GL10.GL_FLOAT, 0, this.mVertexBuffer);
	gl.glLineWidth(this.mWidth);
	gl.glDrawArrays(GL10.GL_LINES, 0, this.mVerticesCount);
	gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
	gl.glDisable(GL10.GL_ALPHA_BITS);
	gl.glDisable(GL10.GL_TEXTURE_2D);
	gl.glPopMatrix();
    }

    @Override
    public void update(long elapsedTime)
    {
    }

    // Extra class methods

    public void setLineWidth(float width)
    {
	mWidth = width;
    }

    public float getLineWidth()
    {
	return mWidth;
    }
}
